//
//  E7Town.cpp
//  EndlessBattle
//
//  Created by cc on 12-3-17.
//  Copyright (c) 2012年 PalmGame. All rights reserved.
//

#include "E7Town.h"

#include "E7Logic.h"

CE7Town::CE7Town()
{
    s_pLogic->create_town_count++ ;
}

CE7Town::~CE7Town()
{
    m_listUnitIDs.clear() ;
    m_listCellIDs.clear() ;
    s_pLogic->delete_town_count++ ;
}

bool CE7Town::InitData(int nID, int countryid, int gold)
{
//    printf("town init data : [%d]\n", nID) ;
    m_nID = nID ;
    m_nCountryID = countryid ;
    m_nGold = gold ;
//    m_nOutGold = 0 ;
    m_nInGold = 0 ;
    m_listUnitIDs.clear() ;
    m_listCellIDs.clear() ;

    CE7Country* pCountry = s_pLogic->GetSelectCountryInfo(m_nCountryID) ;
    pCountry->AddTown(m_nID) ;

    return true ;
}

bool CE7Town::ResetCityCell()
{
    int count = 0 ;

    CE7Cell* pCell = NULL ;
    CE7Unit* pUnit = NULL ;
    for (CELL_ID_LIST::iterator itr = m_listCellIDs.begin(); itr != m_listCellIDs.end(); ++itr)
    {
        pCell = s_pLogic->ActiveMap()->GetSelectCellInfo((*itr)) ;
        pUnit = s_pLogic->GetSelectUnitInfo(pCell->GetUnitID()) ;
        if (NULL != pUnit && UV_CITY == pUnit->GetUV())
        {
            if (0 == count)
            {
                ++count ;
            }
            else
            {
                pCell->SetUnitID(-1) ;
                DelUnit(pUnit->GetID()) ;
                pCell->UpdateUV() ;
            }
        }
    }

//    printf("debug info reset city cell == %d\n", count) ;
    if (0 == count)
    {
        // create city unit.
        CELL_ID_LIST::iterator itr_cellid = m_listCellIDs.begin() ;
        for (int i = 0; i < (int)(m_listCellIDs.size()/2); ++i)
        {
            ++itr_cellid ;
        }
        CE7Unit* pNewUnit = new CE7Unit() ;
        pNewUnit->Create(s_pLogic->GetNewUnitID(), UV_CITY, m_nCountryID, m_nID, (*itr_cellid), false) ;
        s_pLogic->AddUnitInfo(pNewUnit) ;

        AddUnit(pNewUnit->GetID()) ;
        CE7Cell* pTempCell = s_pLogic->ActiveMap()->GetSelectCellInfo((*itr_cellid)) ;
        pTempCell->SetUnitID(pNewUnit->GetID()) ;
        pTempCell->UpdateUV() ;
    }

    return true ;
}

bool CE7Town::Destroy()
{
    if (1 == m_listCellIDs.size())
    {
        CELL_ID_LIST::iterator itr = m_listCellIDs.begin() ;
        CE7Cell* pCell = s_pLogic->ActiveMap()->GetSelectCellInfo((*itr)) ;
        if (NULL == pCell)
        {
            printf("CE7Town::Destroy ERROR\n") ;
            return false ;
        }
        pCell->SetTownID(-1) ;

        CE7Unit* pUnit = s_pLogic->GetSelectUnitInfo(pCell->GetUnitID()) ;
        if (NULL != pUnit)
        {
            if (UV_CITY == pUnit->GetUV())
            {
                pUnit->SetUV(UV_TREE) ;
            }
            else if (UV_SOLDIER_1 == pUnit->GetUV() || UV_SOLDIER_2 == pUnit->GetUV() || UV_SOLDIER_3 == pUnit->GetUV())
            {
                pUnit->SetUV(UV_DEAD) ;
            }
            pUnit->SetTownID(-1) ;
        }
    }

    CE7Country* pCountry = s_pLogic->GetSelectCountryInfo(m_nCountryID) ;
    pCountry->DelTown(m_nID) ;

    return true ;
}

bool CE7Town::AddCell(int nID)
{
//    printf("add cell [%d] to town [%d]\n", nID, m_nID) ;
    for (CELL_ID_LIST::iterator itr = m_listCellIDs.begin(); itr != m_listCellIDs.end(); ++itr)
    {
        if ((*itr) == nID)
        {
            CE7Cell* pCell = s_pLogic->ActiveMap()->GetSelectCellInfo(nID) ;
            printf("debug info: [%d][%d]\n", pCell->GetTownID(), m_nID) ;
            printf("town add cell error : [%d] was added size [%lu]\n", nID, m_listCellIDs.size()) ;
            return false ;
        }
    }

    // process cell info.
    CE7Cell* pCell = s_pLogic->ActiveMap()->GetSelectCellInfo(nID) ;
    pCell->SetTownID(m_nID) ;
    pCell->SetCountryID(m_nCountryID) ;
    if (-1 != pCell->GetUnitID())
    {
        AddUnit(pCell->GetUnitID()) ;
    }

    m_listCellIDs.push_back(nID) ;

    return true ;
}

bool CE7Town::DelCell(int nID)
{
//    printf("enter del cell function [%lu]\n", m_listCellIDs.size()) ;
    // process cell info.
    CE7Cell* pCell = s_pLogic->ActiveMap()->GetSelectCellInfo(nID) ;
    bool city_flag = false ;
    pCell->SetTownID(-1) ;
    if (-1 != pCell->GetUnitID())
    {
        CE7Unit* pUnit = s_pLogic->GetSelectUnitInfo(pCell->GetUnitID()) ;
        if (UV_CITY == pUnit->GetUV())
        {
            city_flag = true ;
        }
        DelUnit(pCell->GetUnitID()) ;
    }

    bool erase_flag = false ;
    for (CELL_ID_LIST::iterator itr = m_listCellIDs.begin(); itr != m_listCellIDs.end(); ++itr)
    {
        if ((*itr) == nID)
        {
            m_listCellIDs.erase(itr) ;
            erase_flag = true ;
            break ;
        }
    }

    if (1 == m_listCellIDs.size())
    {
        if (erase_flag)
        {
            return true ;
        }

        printf("town delete cell error - 1: [%d] is not found\n", nID) ;
        return false ;
    }

    if (city_flag)
    {
        ResetCityCell() ;
    }

//    printf("del cell function - 2 [%lu]\n", m_listCellIDs.size()) ;

    if (erase_flag)
    {
        return true ;
    }

    printf("town delete cell error - 2: [%d] is not found\n", nID) ;
    return false ;
}

bool CE7Town::AttachTown(int nID)
{
//    printf("add town s ------------ [%lu] [%d][%d]\n", m_listCellIDs.size(), nID, m_nID) ;
    CE7Town* pTown = NULL ;
    for (TOWN_INFO_LIST::iterator itr = s_pLogic->m_listTown.begin(); itr != s_pLogic->m_listTown.end(); ++itr)
    {
        if ((*itr)->GetID() == nID)
        {
            pTown = (*itr) ;

            // attach golds.
            m_nGold += pTown->GetGold() ;
            
            // add cells.
            for (CELL_ID_LIST::iterator itr_id = pTown->m_listCellIDs.begin(); itr_id != pTown->m_listCellIDs.end(); ++itr_id)
            {
                AddCell((*itr_id)) ;
            }
            s_pLogic->DelSelectTownInfo((*itr)->GetID()) ;
            ResetCityCell() ;
            break ;
        }
    }

    Balance() ;

//    printf("add town e ------------ [%lu] [%d][%d]\n", m_listCellIDs.size(), nID, m_nID) ;
    return true ;
}

bool CE7Town::CheckNeighborCell(CE7Cell* pStart)
{
    for (int i = 0; i < 6; ++i)
    {
        CE7Cell* pTemp = pStart->GetNeighborPointer(i) ;
        if (NULL == pTemp)
        {
            continue ;
        }
        if (-1 == pTemp->GetCountryID())
        {
            continue ;
        }
        if (pStart->GetCountryID() == pTemp->GetCountryID())
        {
            return true ;
        }
    }
    return false ;
}

void CE7Town::ChangeCellTownID(CE7Town* pTown, CE7Cell* pStart)
{
    for (int i = 0; i < 6; ++i)
    {
        CE7Cell* pTemp = pStart->GetNeighborPointer(i) ;
        if (NULL == pTemp)
        {
            continue ;
        }
        if (-1 == pTemp->GetCountryID())
        {
            continue ;
        }
        if (pTemp->GetCountryID() == pStart->GetCountryID())
        {
            DetachCell(pTemp->GetID()) ;
            if (pTown->AddCell(pTemp->GetID()))
            {
                ChangeCellTownID(pTown, pTemp) ;
            }
        }
    }
}

static CELL_ID_LIST s_listFilter ;
void CE7Town::FilterDetachCell(CE7Cell* pStart)
{
    for (int i = 0; i < 6; ++i)
    {
        CE7Cell* pTemp = pStart->GetNeighborPointer(i) ;
        if (NULL == pTemp)
        {
            continue ;
        }
        if (-1 == pTemp->GetCountryID())
        {
            continue ;
        }
        if (pStart->GetCountryID() == pTemp->GetCountryID())
        {
            bool flag = false ;
            for (CELL_ID_LIST::iterator itr = s_listFilter.begin(); itr != s_listFilter.end(); ++itr)
            {
                if (*itr == pTemp->GetID())
                {
                    flag = true ;
                    break ;
                }
            }
            if (!flag)
            {
//                printf("filter list push back : [%d]\n", pTemp->GetID()) ;
                s_listFilter.push_back(pTemp->GetID()) ;
                FilterDetachCell(pTemp) ;
            }
        }
    }
}

void CE7Town::DetachCell(int nID)
{
//    bool flag = false ;
    for (CELL_ID_LIST::iterator itr = m_listCellIDs.begin(); itr != m_listCellIDs.end(); ++itr)
    {
        if ((*itr) == nID)
        {
            printf("detach cell [%d] from town [%d]\n", nID, m_nID) ;
            m_listCellIDs.erase(itr) ;
            CE7Cell* pCell = s_pLogic->ActiveMap()->GetSelectCellInfo(nID) ;
            pCell->SetTownID(-1) ;

            if (-1 != pCell->GetUnitID())
            {
                UNIT_ID_LIST::iterator itr_unitid = m_listUnitIDs.begin() ;
                for (; itr_unitid != m_listUnitIDs.end(); ++itr_unitid)
                {
                    if (*itr_unitid == pCell->GetUnitID())
                    {
                        m_listUnitIDs.erase(itr_unitid) ;
                        break ;
                    }
                }
            }

            break ;
        }
    }
}

bool CE7Town::DetachTown()
{
//    printf("enter CE7Town::DetachTown [%lu] [%lu]\n", m_listCellIDs.size(), m_listUnitIDs.size()) ;
    // find city cell.
    CE7Cell* pCity = NULL ;
    for (UNIT_ID_LIST::iterator itr = m_listUnitIDs.begin(); itr != m_listUnitIDs.end(); ++itr)
    {
        CE7Unit* pUnit = s_pLogic->GetSelectUnitInfo(*itr) ;
        if (NULL == pUnit)
        {
            printf("CE7Town::DetachTown debug mode unit info: [%lu][%d][%d]\n",
                   s_pLogic->m_listUnit.size(), s_pLogic->create_unit_count, s_pLogic->delete_unit_count) ;
//            continue ;
        }
        if (UV_CITY == pUnit->GetUV())
        {
            pCity = s_pLogic->ActiveMap()->GetSelectCellInfo(pUnit->GetCellID()) ;
            break ;
        }
    }
    if (NULL == pCity)
    {
        printf("exit CE7Town::DetachTown - NULL == pCity\n") ;
        return false ;
    }

    CELL_ID_LIST listTemp ;
    s_listFilter.clear() ;

    printf("CE7Town::DetachTown all size - 0: [%lu][%lu][%lu]\n",
           m_listCellIDs.size(), s_listFilter.size(), listTemp.size()) ;

    s_listFilter.push_back(pCity->GetID()) ;

    printf("push back [%d]\n", pCity->GetID()) ;
    FilterDetachCell(pCity) ;
    printf("CE7Town::DetachTown all size - 1: [%lu][%lu][%lu]\n",
           m_listCellIDs.size(), s_listFilter.size(), listTemp.size()) ;

    CELL_ID_LIST::iterator itr_filter, itr_temp, itr_cellid ;
    bool flag ;
    for (itr_cellid = m_listCellIDs.begin(); itr_cellid != m_listCellIDs.end(); ++itr_cellid)
    {
        flag = true ;
        for (itr_filter = s_listFilter.begin(); itr_filter != s_listFilter.end(); ++itr_filter)
        {
            if ((*itr_cellid) == (*itr_filter))
            {
                flag = false ;
                break ;
            }
        }
        if (flag)
        {
            listTemp.push_back((*itr_cellid)) ;
        }
    }
    printf("CE7Town::DetachTown all size - 2: [%lu][%lu][%lu]\n",
           m_listCellIDs.size(), s_listFilter.size(), listTemp.size()) ;

    if (0 == listTemp.size())
    {
        printf("exit CE7Town::DetachTown - 0 == listTemp.size()\n") ;
        return false ;
    }

    if (1 == listTemp.size())
    {
        CELL_ID_LIST::iterator itr = listTemp.begin() ;
        DetachCell(*itr) ;
        CE7Cell* pDetachCell = s_pLogic->ActiveMap()->GetSelectCellInfo(*itr) ;
        if (-1 != pDetachCell->GetUnitID())
        {
            CE7Unit* pDetachUnit = s_pLogic->GetSelectUnitInfo(pDetachCell->GetUnitID()) ;
            if (UV_SOLDIER_1 == pDetachUnit->GetUV() || UV_SOLDIER_2 == pDetachUnit->GetUV() || UV_SOLDIER_3 == pDetachUnit->GetUV())
            {
                pDetachUnit->SetUV(UV_DEAD) ;
            }
            else if (UV_CITY == pDetachUnit->GetUV())
            {
                pDetachUnit->SetUV(UV_TREE) ;
            }
        }
        printf("exit CE7Town::DetachTown - 1 == listTemp.size()\n") ;
        return false ;
    }

    for (CELL_ID_LIST::iterator itr = listTemp.begin(); itr != listTemp.end(); ++itr)
    {
        CE7Cell* pNewStart = s_pLogic->ActiveMap()->GetSelectCellInfo(*itr) ;
        if (NULL == pNewStart)
        {
            continue ;
        }
        if (CheckNeighborCell(pNewStart))
        {
            // create new town.
            CE7Town* pNewTown = new CE7Town() ;
            pNewTown->InitData(s_pLogic->GetNewTownID(), m_nCountryID, 0) ;
            s_pLogic->AddTownInfo(pNewTown) ;
            DetachCell(pNewStart->GetID()) ;
            pNewTown->AddCell(pNewStart->GetID()) ;
            ChangeCellTownID(pNewTown, pNewStart) ;
            pNewTown->ResetCityCell() ;
            printf("create new town ==== [%lu][%lu]\n", pNewTown->m_listCellIDs.size(), pNewTown->m_listUnitIDs.size()) ;
            break ;
        }
        else
        {
            DetachCell(pNewStart->GetID()) ;
            CE7Cell* pDetachCell = s_pLogic->ActiveMap()->GetSelectCellInfo(*itr) ;
            if (-1 != pDetachCell->GetUnitID())
            {
                CE7Unit* pDetachUnit = s_pLogic->GetSelectUnitInfo(pDetachCell->GetUnitID()) ;
                if (UV_SOLDIER_1 == pDetachUnit->GetUV() || UV_SOLDIER_2 == pDetachUnit->GetUV() || UV_SOLDIER_3 == pDetachUnit->GetUV())
                {
                    pDetachUnit->SetUV(UV_DEAD) ;
                }
                else if (UV_CITY == pDetachUnit->GetUV())
                {
                    pDetachUnit->SetUV(UV_TREE) ;
                }
            }
        }
    }

//    printf("continue CE7Town::DetachTown\n") ;
    return true ;
}

bool CE7Town::AddUnit(int nID)
{
    for (UNIT_ID_LIST::iterator itr = m_listUnitIDs.begin(); itr != m_listUnitIDs.end(); ++itr)
    {
        if ((*itr) == nID)
        {
            printf("town add unit error : [%d] was added\n", nID) ;
            CE7Unit* pUnit = s_pLogic->GetSelectUnitInfo(nID) ;
            if (NULL == pUnit)
            {
                printf("CE7Town::AddUnit - ERROR debug mode unit info: [%lu][%d][%d][%d]\n",
                       s_pLogic->m_listUnit.size(), s_pLogic->create_unit_count, s_pLogic->delete_unit_count, nID) ;
            }
            return false ;
        }
    }

    CE7Unit* pUnit = s_pLogic->GetSelectUnitInfo(nID) ;
    if (NULL == pUnit)
    {
        printf("CE7Town::AddUnit NULL == pUnit [%d]\n", nID) ;
        printf("CE7Town::AddUnit debug mode unit info: [%lu][%d][%d]\n",
               s_pLogic->m_listUnit.size(), s_pLogic->create_unit_count, s_pLogic->delete_unit_count) ;
//        return false ;
    }
    pUnit->SetTownID(m_nID) ;
    pUnit->SetCountryID(m_nCountryID) ;

    m_listUnitIDs.push_back(nID) ;

    return true ;
}

bool CE7Town::DelUnit(int nID)
{
    s_pLogic->DelSelectUnitInfo(nID) ;

    for (UNIT_ID_LIST::iterator itr = m_listUnitIDs.begin(); itr != m_listUnitIDs.end(); ++itr)
    {
        if ((*itr) == nID)
        {
            m_listUnitIDs.erase(itr) ;
            return true ;
        }
    }

    printf("town delete unit error : [%d] is not found\n", nID) ;
    return false ;
}

bool CE7Town::SetAllUnitDead()
{
    CE7Unit* pUnit = NULL ;
    for (UNIT_ID_LIST::iterator itr = m_listUnitIDs.begin(); itr != m_listUnitIDs.end(); ++itr)
    {
        pUnit = s_pLogic->GetSelectUnitInfo((*itr)) ;
        if (UV_SOLDIER_1 == pUnit->GetUV() || UV_SOLDIER_2 == pUnit->GetUV() || UV_SOLDIER_3 == pUnit->GetUV())
        {
            pUnit->SetUV(UV_DEAD) ;
        }
    }

    CE7Cell* pCell = NULL ;
    for (CELL_ID_LIST::iterator itr = m_listCellIDs.begin(); itr != m_listCellIDs.end(); ++itr)
    {
        pCell = s_pLogic->ActiveMap()->GetSelectCellInfo((*itr)) ;
        pCell->UpdateUV() ;
    }

    return true ;
}

void CE7Town::Balance()
{
    m_nInGold = 0 ;

//    printf("now gold - 1: [%d][%d][%d]\n", m_nGold, m_nOutGold, m_nInGold) ;
    CELL_ID_LIST::iterator itr_cellid ;
    CELL_INFO_LIST::iterator itr_cellinfo ;
    CE7Cell* pCell = NULL ;
    for (itr_cellid = m_listCellIDs.begin(); itr_cellid != m_listCellIDs.end(); ++itr_cellid)
    {
        pCell = s_pLogic->ActiveMap()->GetSelectCellInfo((*itr_cellid)) ;
        if (UV_NONE == pCell->GetToNeighborUV())
        {
            m_nInGold += 2 ;
        }
        else
        {
            m_nInGold += UNIT_IN_GOLD_ARRAY[pCell->GetToNeighborUV()] ;
        }
    }
//    printf("now gold - 2: [%d][%d][%d]\n", m_nGold, m_nOutGold, m_nInGold) ;

    m_nGold += m_nInGold ;
    if (m_nInGold <= 0)
    {
        m_nGold += 1 ;
    }

    if (0 > m_nGold && s_pLogic->s_bIsBalance)
    {
        m_nGold = 0 ;
        SetAllUnitDead() ;
    }
}

void CE7Town::BalanceInit()
{
    CELL_ID_LIST::iterator itr_cellid ;
    CELL_INFO_LIST::iterator itr_cellinfo ;
    CE7Cell* pCell = NULL ;
    for (itr_cellid = m_listCellIDs.begin(); itr_cellid != m_listCellIDs.end(); ++itr_cellid)
    {
        pCell = s_pLogic->ActiveMap()->GetSelectCellInfo((*itr_cellid)) ;
        if (UV_NONE == pCell->GetToNeighborUV())
        {
            m_nInGold += 2 ;
        }
        else
        {
            m_nInGold += UNIT_IN_GOLD_ARRAY[pCell->GetToNeighborUV()] ;
        }
    }

    m_nGold = 5 * (m_listCellIDs.size()) ;
//    m_nGold = 100 * (m_listCellIDs.size()) ; // debug mode.
}




























